home *** CD-ROM | disk | FTP | other *** search
- /* Quick and dirty demo application for dissMask routines.
- Written August 1990 by Mike Morton for MacTutor.
- */
- #include "dissMask.h"
-
- /* “dissolve” is just a part of the driver; you’ll probably want
- your own code to call the dissMask____ functions(), although
- your code will look a lot like “dissolve”. */
- static void dissolve (BitMap *srcBits, BitMap *dstBits, Rect *srcRect,
- Rect *dstRect, unsigned short steps);
-
- void main (void)
- { Rect winBounds;
- WindowRecord theWindow;
- Handle scrapHandle;
- long scrapResult;
- long scrapOffset;
- char windowTitle [100];
- BitMap offScreen, winBits;
- short rows, cols;
- EventRecord evt;
- long dummy;
- short clipCopies, clipCount;
- PicHandle thePict;
- short picWidth, picHeight;
- Rect target;
-
- /* Standard Mac init, skipping menus & TE & dialogs: */
- InitGraf (& thePort);
- InitFonts ();
- FlushEvents (everyEvent, 0);
- InitWindows ();
- InitCursor ();
-
- /* We prefer to be run with graphics on the clipboard,
- but protest only feebly if there’s no PICT: */
- strcpy (windowTitle, "Dissolve demo using CopyMask");
- scrapHandle = NewHandle (0L);
- scrapResult = GetScrap (scrapHandle, 'PICT', & scrapOffset);
- if (scrapResult < 0) /* no PICT available? */
- strcat (windowTitle, " (NO PICTURE ON CLIPBOARD)");
- CtoPstr (windowTitle);
-
- /* Steal the main screen, inset a bit, and avoid the menu bar. */
- winBounds = screenBits.bounds;
- InsetRect (& winBounds, 8, 8);
- winBounds.top += 20 + MBarHeight;
-
- /* Make up a new window: */
- NewWindow (& theWindow, & winBounds, windowTitle,
- true, /*visible at first*/ noGrowDocProc,
- -1L, /*frontmost*/ false, /*no go-away box*/
- 0L); /*no refcon*/
- SetPort ((GrafPtr) & theWindow);
- winBits = thePort->portBits; /* remember where onscreen bit image is */
-
- rows = thePort->portRect.bottom - thePort->portRect.top;
- cols = thePort->portRect.right - thePort->portRect.left;
-
- /* Make up a bitmap with the same bounds as the window. */
- offScreen.bounds = thePort->portRect;
- offScreen.rowBytes = (cols + 7) / 8;
- if (offScreen.rowBytes & 1)
- ++offScreen.rowBytes;
- offScreen.baseAddr =
- NewPtrClear (rows * (long) offScreen.rowBytes);
- if (offScreen.baseAddr == 0) /* out of memory? */
- { SysBeep (10); /* be uninformative */
- ExitToShell ();
- }
-
- /* Fill up the offscreen bitmap. If we have a clipboard PICT, tile
- the offscreen bitmap with it; else fill the bitmap with black. */
- SetPortBits (& offScreen);
- if (scrapResult >= 0)
- { thePict = (PicHandle) scrapHandle;
- target = (**thePict).picFrame;
- picWidth = target.right - target.left;
- picHeight = target.bottom - target.top;
-
- /* Tile the offscreen image with copies of the PICT. */
- clipCopies = 0;
- target.top = 0;
- target.bottom = picHeight;
- while (target.top < thePort->portRect.bottom)
- { target.left = 0;
- target.right = picWidth;
- while (target.left < thePort->portRect.right)
- { DrawPicture (thePict, & target);
- OffsetRect (& target, picWidth, 0);
- ++clipCopies;
- }
- OffsetRect (& target, 0, picHeight);
- }
-
- }
- else /* no PICT? */
- FillRect (& thePort->portRect, black); /* paint it black, you devil */
- SetPortBits (& winBits);
-
- /* Bring in ALL this to show the speed of a nearly-full-screen dissolve. */
- dissolve (& offScreen, & theWindow.port.portBits,
- & thePort->portRect, & thePort->portRect, 10);
- Delay (60L, & dummy);
- EraseRect (& thePort->portRect);
-
- /* If we have a clipboard PICT, dissolve these things in at
- varying speeds -- note the last parameter to dissolve(). */
- if (scrapResult >= 0)
- { clipCount = 1;
- target.top = 0;
- target.bottom = picHeight;
- while (target.top < thePort->portRect.bottom)
- { target.left = 0;
- target.right = picWidth;
- while (target.left < thePort->portRect.right)
- { /* The first image dissolves in 20 steps; the last
- one in fewer. */
- dissolve (& offScreen, & theWindow.port.portBits,
- & target, & target,
- 20 * (clipCopies - clipCount) / clipCopies);
- OffsetRect (& target, picWidth, 0);
- ++clipCount;
- }
- OffsetRect (& target, 0, picHeight);
- }
- Delay (60L, & dummy);
- EraseRect (& thePort->portRect);
- }
-
- /* Let ’em draw selections to be dissolved in. */
- SetWTitle (& theWindow, "\pClick and drag to dissolve … press a key to exit");
- do
- { GetNextEvent (everyEvent, & evt);
- if (evt.what == mouseDown)
- { GlobalToLocal (& evt.where);
- if (PtInRect (evt.where, & thePort->portRect))
- { Point startPt, endPt, curPt;
- Rect frame;
-
- PenPat (gray); PenSize (1, 1); PenMode (patXor);
- startPt = evt.where;
- endPt = evt.where;
- Pt2Rect (startPt, endPt, & frame);
- FrameRect (& frame);
- while (StillDown ())
- { GetMouse (& curPt);
- if (curPt.v < 0) curPt.v = 0; /* hack to avoid mysterious bugs */
- if (! EqualPt (curPt, endPt))
- { FrameRect (& frame);
- endPt = curPt;
- Pt2Rect (startPt, endPt, & frame);
- FrameRect (& frame);
- }
- }
- FrameRect (& frame);
- dissolve (& offScreen, & theWindow.port.portBits,
- & frame, & frame, 20);
-
- }
- else SysBeep (2); /* click outside window */
- } /* end of handling mousedown */
- } while (evt.what != keyDown);
-
- } /* end of main () */
-
- /* dissolve -- A quick driver for dissMask routines. It sets up
- the dissolve and does it in the specified number of iterations. */
- static void dissolve (srcBits, dstBits, srcRect, dstRect, steps)
- BitMap *srcBits, *dstBits;
- Rect *srcRect, *dstRect;
- unsigned short steps;
- { dissMaskInfo info;
- unsigned long pixPerStep;
-
- /* Initialize for the dissolve; if it fails, just copy outright: */
- if (! dissMaskInit (srcRect, & info))
- { CopyBits (srcBits, dstBits, srcRect, dstRect, srcCopy, 0L);
- return;
- }
-
- if (steps == 0) steps = 1;
- pixPerStep = (info.pixLeft / steps) + 1;
-
- /* Main dissolve loop: repeatedly darken the mask
- bitmap and CopyMask through it. */
- HideCursor ();
- while (info.pixLeft)
- { dissMaskNext (& info, pixPerStep);
- CopyMask (srcBits, & info.maskMap, dstBits,
- srcRect, & info.maskRect, dstRect);
- }
-
- /* Clean up: */
- ShowCursor ();
- dissMaskFinish (& info);
- } /* end of dissolve () */
-